package com.hmall.common.utils;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.util.concurrent.ListenableFutureCallback;

/**
 * @author ：zhengsuyang
 * @description：
 * @date ：2025/11/7 19:30
 */
@RequiredArgsConstructor
@Slf4j
public class RabbitMqHelper {

    private final RabbitTemplate rabbitTemplate;
    private Integer retries = 0;

    public void sendMessage(String exchange, String routingKey, Object msg){
        rabbitTemplate.convertAndSend(exchange, routingKey, msg);
    }

    public void sendDelayMessage(String exchange, String routingKey, Object msg, int delay){
        rabbitTemplate.convertAndSend(exchange, routingKey, msg, new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                message.getMessageProperties().setDelay(delay);
                return message;
            }
        });
    }

    public synchronized void sendMessageWithConfirm(String exchange, String routingKey, Object msg, int maxRetries){
        if (retries >= maxRetries) {
            log.info("消息发送失败，已重试{}次，不再重试", maxRetries);
            return;
        }
        CorrelationData cd = new CorrelationData();
        cd.getFuture().addCallback(new ListenableFutureCallback<CorrelationData.Confirm>() {
            @Override
            public void onFailure(Throwable ex) {

            }

            @Override
            public void onSuccess(CorrelationData.Confirm result) {
                if (result.isAck()) {
                    log.info("消息发送成功");
                }
                else {
                    retries++;
                    log.info("消息发送失败");
                    sendMessageWithConfirm(exchange, routingKey, msg, maxRetries);
                }
            }
        });
        rabbitTemplate.convertAndSend(exchange, routingKey, msg, cd);
    }
}